package payment

import (
	"cloud_android_backend/pkg/models/orders"
	"cloud_android_backend/pkg/models/products"
	"cloud_android_backend/pkg/models/resources"
	user "cloud_android_backend/pkg/models/users"
	"cloud_android_backend/pkg/modules/realphone"
	"fmt"
	"github.com/golang/glog"
	"github.com/jinzhu/gorm"
	"modules.tenxcloud.com/common/composite"
	"strconv"
	"time"
)

type Balance struct {
	Amount  float64
	UserId  string
	OrderId int64
}

func (b *Balance) Payment() (string, error) {
	db, err := composite.Database.GetOrm()
	if err != nil {
		glog.Errorf("get orm failed, error %v", err)
		return "", err
	}
	userModel := user.User{UserID: b.UserId}
	err = db.Transaction(func(tx *gorm.DB) error {
		if err := userModel.GetByUserIdForUpdate(tx); err != nil {
			glog.Errorf("get user failed, error %v", err)
			return err
		}
		if userModel.Balance < b.Amount {
			glog.Errorf("user balance not enough")
			return fmt.Errorf("用户余额不足")
		}
		userModel.Balance -= b.Amount
		err = userModel.Update(tx, &userModel)
		//err = tx.Table("users").Where("user_id = ?", userModel.UserID).Save(&userModel).Error
		if err != nil {
			glog.Errorf("update user failed, error %v", err)
			return err
		}
		//添加账户余额流水表
		accountTrans := orders.AccountTransactions{
			UserId:      userModel.UserID,
			Amount:      -b.Amount,
			Description: "云机购买",
			Type:        orders.AccountTransactionsTypeWithdraw,
			CreatedAt:   time.Now(),
			OrderId:     b.OrderId,
			Balance:     userModel.Balance,
		}
		err = accountTrans.Create(tx)
		if err != nil {
			glog.Errorf("create account transaction failed:err %v", err)
			return err
		}
		orderModel := orders.Orders{Id: b.OrderId}
		if err := orderModel.GetById(db); err != nil {
			glog.Errorf("查询订单失败: %v", err)
			return err
		}
		orderModel.PayTime = time.Now()
		orderModel.ActualAmount = b.Amount
		orderModel.CallbackTime = time.Now()
		orderModel.Status = int(orders.OrderStatus_Success)

		err = orderModel.Update(tx)
		if err != nil {
			glog.Errorf("更新订单失败: %v", err)
			return err
		}
		switch orderModel.OrderType {
		case int(orders.OrderTypeInstance):
			packageInfo := products.ProductPackages{Id: orderModel.PackageId}
			err = packageInfo.GetById(db)
			if err != nil {
				glog.Errorf("get product package info failed:err %v", err)
				return err
			}
			instanceModel := resources.InstanceUses{OrderId: orderModel.Id}
			instanceList, err := instanceModel.GetListByOrderId(tx)
			if err != nil {
				glog.Errorf("get instance use list failed:err %v", err)
				return err
			}
			productModel := products.Products{Id: packageInfo.ProductId}
			err = productModel.GetById(tx)
			if err != nil {
				glog.Errorf("get product info failed:err %v", err)
				return err
			}
			for _, instance := range instanceList {
				instanceModel := &instance
				instanceModel.Status = int(resources.InstanceUseStatusUsing)
				instanceModel.StartTime = time.Now()
				instanceModel.ExpireTime = time.Now().AddDate(0, 0, packageInfo.Duration)
				instanceModel.InstanceName = "云机" + strconv.FormatInt(instanceModel.Id, 10)
				err = instanceModel.Update(tx)
				if err != nil {
					glog.Errorf("update instance use failed:err %v", err)
					return err
				}
				if productModel.Type == 1 {
					go func(id int64) {
						if err := realphone.EasyToRecreateNewInstance(id, b.UserId); err != nil {
							glog.Error(err)
						}
					}(instance.Id)
				} else {
					instancesModel := resources.Instances{Id: instance.InstanceId}
					err = instancesModel.GetById(tx)
					if err != nil {
						glog.Errorf("get instance failed:err %v", err)
					}
					if instancesModel.AdiTemplateId == 0 {
						instancesModel.AdiTemplateId = 36
					}
					go func(id int64) {
						if err := realphone.ChangeRealPhoneModelAndClearData(id, instancesModel.AdiTemplateId, b.UserId); err != nil {
							glog.Error(err)
						}
					}(instance.Id)
				}

			}

			//TODO:升级实例镜像
			//go instances.InstanceConnect(instanceList)
		case int(orders.OrderTypeRenew):
			packageInfo := products.ProductPackages{Id: orderModel.PackageId}
			err = packageInfo.GetById(db)
			if err != nil {
				glog.Errorf("get product package info failed:err %v", err)
				return err
			}
			instanceModel := resources.InstanceUses{OrderId: orderModel.Id}
			instanceList, err := instanceModel.GetListByOrderId(tx)
			if err != nil {
				glog.Errorf("get instance use list failed:err %v", err)
				return err
			}
			for _, instance := range instanceList {
				instanceModel := &instance
				instanceModel.Status = int(resources.InstanceUseStatusUsing)
				err = instanceModel.Update(tx)
				if err != nil {
					glog.Errorf("update instance use failed:err %v", err)
					return err
				}
				if instance.PrewInstanceId > 0 {
					prewInstanceModel := resources.InstanceUses{Id: instance.PrewInstanceId}
					err = prewInstanceModel.UpdatePartFields(tx, map[string]interface{}{"status": int(resources.InstanceUseStatusExpired)})
					if err != nil {
						glog.Errorf("update instance use failed:err %v", err)
						return err
					}
				}
			}
		}

		return nil
	})
	if err != nil {
		glog.Errorf("transaction failed:err %v", err)
		return "", err
	}
	return "", nil
}

func (b *Balance) GetResultType() ResultType {
	return ""
}
func (b *Balance) GetResult() string {
	return ""
}
